<?php
namespace App\Common\Cla\ClaBase\Traits\LinkedTree;

use App\Common as com;
use App\Common\Cla\ClaBase\Traits\LinkedTree as nameLinkedTree;

trait OfIds {

	/**
	 * @var nameLinkedTree\StaticFun
	 */
	private string $linkedTreeStatic;

	private array $mainIds;

	/**
	 * @param string $linkedTreeStaticClass
	 * @param array $mainId
	 */
	protected function initLinkedTree( string $linkedTreeStaticClass, array $mainIds ) {
		$this->mainIds = $mainIds;
		//
		$this->linkedTreeStatic = $linkedTreeStaticClass;
	}

	/**
	 * @return array
	 */
	public function getMainIds(  ):array {
		return $this->mainIds;
	}

	/**
	 * 检测新的上级是否会形成死循环
	 * @param int $newParentId 新的上级系统分类id
	 * @return bool [false]没有循环 [true]出现死循环
	 */
	public function checkRepeatOfNewUp( int $newParentId ):bool {
		foreach( $this->getMainIds() as $mainId ){
			if( $this->linkedTreeStatic::checkRepeatOfNewUp( $mainId, $newParentId ) ){
				return true;
			}
		}
		return false;
	}

	/**
	 * 获取当前树的所有上级集合
	 * @param int $layerNum 获取的层数（默认：99999）
	 * @return array 返回包含上级树id的层级数组（格式为：array( {层数} => {上级分类id}, 1 => 2 )），层数为0是自身，大于0为上级层数
	 * @todo :o 待优化，要使用数据库存储过程获取
	 * @throws
	 */
	public function getUpReLevelMap( int $layerNum = 99999 ):array {
		$returnData = [];
		foreach( $this->getMainIds() as $mainId ){
			$returnData = com\Lib\Fun\Array_::arrayMerges(
				$returnData,
				$this->linkedTreeStatic::getUpReLevelMap( $mainId, $layerNum )
			);
		}
		return $returnData;
	}

	/**
	 * 获取树的上一层树id
	 * @param int $currentId 要获取指定分类的上层树id
	 * @return int 返回上级树id，没有则返回0。
	 */
	public function getUpId( int $currentId ):int {
		return $this->linkedTreeStatic::getUpId( $currentId );
	}

	/**
	 * 取当前表模型
	 * @return com\Model\Base\DataUnit
	 */
	protected function newDataUnit():com\Model\Base\DataUnit {
		return $this->linkedTreeStatic::newDataUnit();
	}

	/**
	 * 获取下级id（单级）
	 * @return array 返回下级包含id的数组（如:[1,2,3... ]），没有上级则返回空数组。
	 */
	public function getDownIds(){
		$returnData = [];
		foreach( $this->getMainIds() as $mainId ){
			$returnData = com\Lib\Fun\Array_::arrayMerges(
				$returnData,
				$this->linkedTreeStatic::getDownIds( $mainId )
			);
		}
		//
		return com\Lib\Utils\ArrayHelper::makeOfNew( $returnData )->unique()->toArray();
	}

	/**
	 * 获取下级id（多级）(以地图的形式返回)
	 * @param int $levelNum 获取的最大级别[默认：888]
	 * @return array [ {下级1-id} => [ 2, 3 ], ... ] (层数从近到远)
	 */
	public function getAllDownIdsReMap( $levelNum = 888 ){
		$returnData = [];
		foreach( $this->getMainIds() as $mainId ){
			$returnData = com\Lib\Fun\Array_::arrayMergeOfParam(
				$returnData,
				$this->linkedTreeStatic::getAllDownIdsReMap( $mainId, $levelNum ),
				[
					'mergeIntKey' => 1
				]
			);
		}
		return com\Lib\Fun\Array_::arrayUniqueOfMany( $returnData );
	}

	/**
	 * 将“下级地图id”转成列表id
	 * @param int $levelNum 获取的最大级别[默认：888]
	 * @return array 下级列表id数组，（如:[1,2,3... ]），没有上级则返回空数组。
	 */
	public function getAllDownIds( $levelNum = 888 ):array {
		$returnData = [];
		foreach( $this->getMainIds() as $mainId ){
			$returnData = com\Lib\Fun\Array_::arrayMerge(
				$returnData,
				$this->linkedTreeStatic::getAllDownIds( $mainId, $levelNum )
			);
		}
		return com\Lib\Utils\ArrayHelper::makeOfNew( $returnData )->unique()->toArray();
	}

	/**
	 * 是否为上级，并返回上级级别[最大支持999级]
	 * @param int $upId 要判断的上级id
	 * @return bool
	 */
	public function isUp( int $upId ):bool {
		return $this->isUpReLevel( $upId  ) > 0;
	}

	/**
	 * 是否为上级，并返回上级级别[最大支持999级]
	 * @param int $upId 要判断的上级id
	 * @return int 返回上级级别1、2、3、...，不是上级返回0。
	 */
	public function isUpReLevel( int $upId ):int {
		foreach( $this->getMainIds() as $mainId ){
			if( $this->linkedTreeStatic::isUpReLevel( $this->$mainId(), $upId ) ){
				return true;
			}
		}
		return false;
	}

	/**
	 * 是否为下级，并返回下级级别[最大支持999级]
	 * @param int $sonId 要判断的下级id
	 * @return int 返回下级级别1、2、3、...，不是下级返回0。
	 */
	public function isDown( int $sonId ):bool {
		return $this->isDownReLevel( $sonId  ) > 0;
	}

	/**
	 * 是否为下级，并返回下级级别[最大支持999级]
	 * @param int $sonId 要判断的下级id
	 * @return int 返回下级级别1、2、3、...，不是下级返回0。
	 */
	public function isDownReLevel( int $sonId ):int {
		foreach( $this->getMainIds() as $mainId ){
			if( $this->linkedTreeStatic::isDownReLevel( $this->$mainId(), $sonId ) ){
				return true;
			}
		}
		return false;
	}

}
